home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Mac / Lib / Audio_mac.py next >
Encoding:
Python Source  |  2000-06-23  |  2.7 KB  |  123 lines

  1. QSIZE = 100000
  2. error='Audio_mac.error'
  3.  
  4. class Play_Audio_mac:
  5.  
  6.     def __init__(self, qsize=QSIZE):
  7.         self._chan = None
  8.         self._qsize = qsize
  9.         self._outrate = 22254
  10.         self._sampwidth = 1
  11.         self._nchannels = 1
  12.         self._gc = []
  13.         self._usercallback = None
  14.  
  15.     def __del__(self):
  16.         self.stop()
  17.         self._usercallback = None
  18.  
  19.     def wait(self):
  20.         import time
  21.         while self.getfilled():
  22.             time.sleep(0.1)
  23.         self._chan = None
  24.         self._gc = []
  25.  
  26.     def stop(self, quietNow = 1):
  27.         ##chan = self._chan
  28.         self._chan = None
  29.         ##chan.SndDisposeChannel(1)
  30.         self._gc = []
  31.  
  32.     def setoutrate(self, outrate):
  33.         self._outrate = outrate
  34.  
  35.     def setsampwidth(self, sampwidth):
  36.         self._sampwidth = sampwidth
  37.  
  38.     def setnchannels(self, nchannels):
  39.         self._nchannels = nchannels
  40.  
  41.     def writeframes(self, data):
  42.         import time
  43.         from Sound import *
  44.         import struct
  45.         import MacOS
  46.         if not self._chan:
  47.             import Snd
  48.             self._chan = Snd.SndNewChannel(5, 0, self._callback)
  49.         nframes = len(data) / self._nchannels / self._sampwidth
  50.         if len(data) != nframes * self._nchannels * self._sampwidth:
  51.             raise error, 'data is not a whole number of frames'
  52.         while self._gc and \
  53.               self.getfilled() + nframes > \
  54.                 self._qsize / self._nchannels / self._sampwidth:
  55.             time.sleep(0.1)
  56.         if self._sampwidth == 1:
  57.             import audioop
  58.             data = audioop.add(data, '\x80'*len(data), 1)
  59.         h1 = struct.pack('llhhllbbl',
  60.             id(data)+MacOS.string_id_to_buffer,
  61.             self._nchannels,
  62.             self._outrate, 0,
  63.             0,
  64.             0,
  65.             extSH,
  66.             60,
  67.             nframes)
  68.         h2 = 22*'\0'
  69.         h3 = struct.pack('hhlll',
  70.             self._sampwidth*8,
  71.             0,
  72.             0,
  73.             0,
  74.             0)
  75.         header = h1+h2+h3
  76.         self._gc.append((header, data))
  77.         self._chan.SndDoCommand((bufferCmd, 0, header), 0)
  78.         self._chan.SndDoCommand((callBackCmd, 0, 0), 0)
  79.  
  80.     def _callback(self, *args):
  81.         del self._gc[0]
  82.         if self._usercallback:
  83.             self._usercallback()
  84.             
  85.     def setcallback(self, callback):
  86.         self._usercallback = callback
  87.  
  88.     def getfilled(self):
  89.         filled = 0
  90.         for header, data in self._gc:
  91.             filled = filled + len(data)
  92.         return filled / self._nchannels / self._sampwidth
  93.  
  94.     def getfillable(self):
  95.         return (self._qsize / self._nchannels / self._sampwidth) - self.getfilled()
  96.  
  97.     def ulaw2lin(self, data):
  98.         import audioop
  99.         return audioop.ulaw2lin(data, 2)
  100.  
  101. def test():
  102.     import aifc
  103.     import macfs
  104.     fss, ok = macfs.PromptGetFile("Select an AIFF soundfile", "AIFF")
  105.     if not ok: return
  106.     fn = fss.as_pathname()
  107.     af = aifc.open(fn, 'r')
  108.     print af.getparams()
  109.     p = Play_Audio_mac()
  110.     p.setoutrate(af.getframerate())
  111.     p.setsampwidth(af.getsampwidth())
  112.     p.setnchannels(af.getnchannels())
  113.     BUFSIZ = 10000
  114.     while 1:
  115.         data = af.readframes(BUFSIZ)
  116.         if not data: break
  117.         p.writeframes(data)
  118.         print 'wrote', len(data), 'space', p.getfillable()
  119.     p.wait()
  120.  
  121. if __name__ == '__main__':
  122.     test()
  123.